package tech.blueglacier.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.message.MaximalBodyDescriptor;
import org.apache.james.mime4j.stream.BodyDescriptor;
import tech.blueglacier.codec.EnhancedDecoderUtil;
import tech.blueglacier.disposition.ContentDispositionDecoder;

import java.util.Map;

public class NameUtil {

    public static String getAttachmentNameFromDispositionParameters(BodyDescriptor bd) {
        //Refer RFC : 2047 for mime word decoding
        //Refer RFC : 2183 for Content-Disposition Header Field
        if (!(bd instanceof MaximalBodyDescriptor)) {
            return null;
        }

        try {
            String attachmentName = getDecodedWord(((MaximalBodyDescriptor) bd).getContentDispositionFilename());
            if (StringUtils.isEmpty(attachmentName)) {
                //Handling case where RFC 2183 is not properly implemented by tech.blueglacier.email creating client.
                attachmentName = getDecodedWord(((MaximalBodyDescriptor) bd).getContentDispositionParameters().get("name"));
            }
            //Added case for supporting RFC 2184 'Parameter Value Character Set and Language Information'
            // this is currently not supported in mime4j (version 0.7.2)
            if (StringUtils.isEmpty(attachmentName)) {
                attachmentName = getDecodedDispositionFileName(bd);
            }

            return attachmentName;
        } catch (Exception e) {
            return null;
        }
    }

    private static String getDecodedWord(String filename) throws IllegalArgumentException {
        return EnhancedDecoderUtil.concatAndDecodeWords(filename);
    }

    private static String getDecodedDispositionFileName(BodyDescriptor bd) throws MimeException {
        return ContentDispositionDecoder.decodeDispositionFileName(((MaximalBodyDescriptor) bd).getContentDispositionParameters());
    }

    public static String getAttachmentNameFromContentTypeParameters(BodyDescriptor bd) {
        if (!(bd instanceof MaximalBodyDescriptor)) {
            return null;
        }

        try {
            String attachmentName = null;
            String nameKey;
            Map<String, String> contentTypeParameters = ((MaximalBodyDescriptor) bd).getContentTypeParameters();
            if (contentTypeParameters.containsKey(nameKey = "name")
                    || contentTypeParameters.containsKey(nameKey = "NAME")
                    || contentTypeParameters.containsKey(nameKey = "Name")) {
                attachmentName = contentTypeParameters.get(nameKey);
            }

            return getDecodedWord(attachmentName);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Content tech.blueglacier.disposition 'filename' is more standard, so it's taken as default first
     * Content type 'name' is other alternative so it's taken as alternative too
     */
    public static String getAttachmentName(BodyDescriptor bd) {
        String attachmentName = NameUtil.getAttachmentNameFromDispositionParameters(bd);
        return !StringUtils.isEmpty(attachmentName) ? attachmentName : NameUtil.getAttachmentNameFromContentTypeParameters(bd);
    }
}
